package com.xueke.crawler.helper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * Created by weibo on 2017/5/13.
 *
 * @author weibo.qin
 * @version 2017/5/13
 */
public class HttpUtil {
	/**
	 * 发送GET请求.
	 *
	 * @param url
	 *            GET请求地址
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doGet(String url) {

		return HttpUtil.doGet(url, null, null, 0);
	}

	/**
	 * 发送GET请求.
	 *
	 * @param url
	 *            GET请求地址
	 * @param headerMap
	 *            GET请求头参数容器
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doGet(String url, Map headerMap) {

		return HttpUtil.doGet(url, headerMap, null, 0);
	}

	/**
	 * 发送GET请求.
	 *
	 * @param url
	 *            GET请求地址
	 * @param proxyUrl
	 *            代理服务器地址
	 * @param proxyPort
	 *            代理服务器端口号
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doGet(String url, String proxyUrl, int proxyPort) {

		return HttpUtil.doGet(url, null, proxyUrl, proxyPort);
	}

	/**
	 * 发送GET请求.
	 *
	 * @param url
	 *            GET请求地址
	 * @param headerMap
	 *            GET请求头参数容器
	 * @param proxyUrl
	 *            代理服务器地址
	 * @param proxyPort
	 *            代理服务器端口号
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doGet(String url, Map headerMap, String proxyUrl,
			int proxyPort) {

		byte[] content = null;
		HttpClient httpClient = new HttpClient();
		GetMethod getMethod = new GetMethod(url);

		if (headerMap != null) {

			// 头部请求信息
			if (headerMap != null) {

				Iterator iterator = headerMap.entrySet().iterator();
				while (iterator.hasNext()) {

					Map.Entry entry = (Map.Entry) iterator.next();
					getMethod.addRequestHeader(entry.getKey().toString(), entry
							.getValue().toString());
				}
			}
		}

		if (StringUtils.isNotBlank(proxyUrl)) {

			httpClient.getHostConfiguration().setProxy(proxyUrl, proxyPort);
		}

		// 设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
		getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 10000000);
		// postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER ,
		// new DefaultHttpMethodRetryHandler());
		InputStream inputStream = null;
		try {

			if (httpClient.executeMethod(getMethod) == HttpStatus.SC_OK) {

				// 读取内容
				inputStream = getMethod.getResponseBodyAsStream();
				content = IOUtils.toByteArray(inputStream);
			} else {

				System.err.println("Method failed: "
						+ getMethod.getStatusLine());
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {

			IOUtils.closeQuietly(inputStream);
			getMethod.releaseConnection();
		}
		return content;
	}

	/**
	 * 发送GET请求.
	 *
	 * @param url
	 *            GET请求地址
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static String doGetStringResult(String url) {
		return new String(HttpUtil.doGet(url, null, null, 0));
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param parameterMap
	 *            POST请求参数容器
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doPost(String url, Map parameterMap) {

		return HttpUtil.doPost(url, null, parameterMap, null, null, null, null,
				0);
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param requestBody
	 *            POST请求参数容器
	 * @param paramCharset
	 *            参数字符集名称
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static String doPost(String url, String requestBody,
			String contentType, String paramCharset) {

		try {
			return new String(HttpUtil.doPost(url, null, null, requestBody,
					contentType, paramCharset, null, 0), "gb2312");
		} catch (Exception e) {
			return doPost(url, requestBody, contentType, paramCharset);
		}
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param parameterMap
	 *            POST请求参数容器
	 * @param paramCharset
	 *            参数字符集名称
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doPost(String url, Map parameterMap,
			String paramCharset) {

		return HttpUtil.doPost(url, null, parameterMap, null, null,
				paramCharset, null, 0);
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param headerMap
	 *            POST请求头参数容器
	 * @param parameterMap
	 *            POST请求参数容器
	 * @param paramCharset
	 *            参数字符集名称
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doPost(String url, Map headerMap, Map parameterMap,
			String paramCharset) {

		return HttpUtil.doPost(url, headerMap, parameterMap, null, null,
				paramCharset, null, 0);
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param parameterMap
	 *            POST请求参数容器
	 * @param paramCharset
	 *            参数字符集名称
	 * @param proxyUrl
	 *            代理服务器地址
	 * @param proxyPort
	 *            代理服务器端口号
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doPost(String url, Map parameterMap,
			String paramCharset, String proxyUrl, int proxyPort) {

		return HttpUtil.doPost(url, null, parameterMap, null, null,
				paramCharset, proxyUrl, proxyPort);
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param headerMap
	 *            POST请求头参数容器
	 * @param parameterMap
	 *            POST请求参数容器
	 * @param paramCharset
	 *            参数字符集名称
	 * @param proxyUrl
	 *            代理服务器地址
	 * @param proxyPort
	 *            代理服务器端口号
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doPost(String url, Map headerMap, Map parameterMap,
			String requestBody, String contentType, String paramCharset,
			String proxyUrl, int proxyPort) {

		byte[] content = null;
		HttpClient httpClient = new HttpClient();
		PostMethod postMethod = new PostMethod(url);

		if (StringUtils.isNotBlank(paramCharset)) {

			postMethod.getParams().setContentCharset(paramCharset);
			postMethod.getParams().setHttpElementCharset(paramCharset);
		}

		if (headerMap != null) {

			// 头部请求信息
			if (headerMap != null) {

				Iterator iterator = headerMap.entrySet().iterator();
				while (iterator.hasNext()) {

					Map.Entry entry = (Map.Entry) iterator.next();
					postMethod.addRequestHeader(entry.getKey().toString(),
							entry.getValue().toString());
				}
			}
		}
		if (parameterMap != null) {
			Iterator iterator = parameterMap.keySet().iterator();
			while (iterator.hasNext()) {

				String key = (String) iterator.next();
				postMethod.addParameter(key, (String) parameterMap.get(key));
			}
		}

		InputStream inputStream = null;
		try {
			if (StringUtils.isNotBlank(requestBody)) {
				StringRequestEntity entity = new StringRequestEntity(
						requestBody, contentType, paramCharset);
				((EntityEnclosingMethod) postMethod).setRequestEntity(entity);
			}

			if (StringUtils.isNotBlank(proxyUrl)) {

				httpClient.getHostConfiguration().setProxy(proxyUrl, proxyPort);
			}

			// 设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
			postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,
					10000);
			// postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER
			// , new DefaultHttpMethodRetryHandler());

			if (httpClient.executeMethod(postMethod) == HttpStatus.SC_OK) {
				// 读取内容
				inputStream = postMethod.getResponseBodyAsStream();
				content = IOUtils.toByteArray(inputStream);
			} else {

				System.err.println("Method failed: "
						+ postMethod.getStatusLine());
			}
		} catch (IOException ex) {

			ex.printStackTrace();
		} finally {

			IOUtils.closeQuietly(inputStream);
			postMethod.releaseConnection();
		}
		return content;
	}

	/**
	 * 发送POST请求.
	 *
	 * @param url
	 *            POST请求地址
	 * @param headerMap
	 *            POST请求头参数容器
	 * @param parameterMap
	 *            POST请求参数容器
	 * @param paramCharset
	 *            参数字符集名称
	 * @param proxyUrl
	 *            代理服务器地址
	 * @param proxyPort
	 *            代理服务器端口号
	 * @return 与当前请求对应的响应内容字节数组
	 */
	public static byte[] doPost(HttpClient httpClient, String url,
			Map headerMap, Map parameterMap, String requestBody,
			String contentType, String paramCharset, String proxyUrl,
			int proxyPort) {

		byte[] content = null;
		PostMethod postMethod = new PostMethod(url);

		if (StringUtils.isNotBlank(paramCharset)) {

			postMethod.getParams().setContentCharset(paramCharset);
			postMethod.getParams().setHttpElementCharset(paramCharset);
		}

		if (headerMap != null) {

			// 头部请求信息
			if (headerMap != null) {

				Iterator iterator = headerMap.entrySet().iterator();
				while (iterator.hasNext()) {

					Map.Entry entry = (Map.Entry) iterator.next();
					postMethod.addRequestHeader(entry.getKey().toString(),
							entry.getValue().toString());
				}
			}
		}
		if (parameterMap != null) {
			Iterator iterator = parameterMap.keySet().iterator();
			while (iterator.hasNext()) {

				String key = (String) iterator.next();
				postMethod.addParameter(key, (String) parameterMap.get(key));
			}
		}

		InputStream inputStream = null;
		try {
			if (StringUtils.isNotBlank(requestBody)) {
				StringRequestEntity entity = new StringRequestEntity(
						requestBody, contentType, paramCharset);
				((EntityEnclosingMethod) postMethod).setRequestEntity(entity);
			}

			if (StringUtils.isNotBlank(proxyUrl)) {

				httpClient.getHostConfiguration().setProxy(proxyUrl, proxyPort);
			}

			// 设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
			postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,
					10000);
			// postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER
			// , new DefaultHttpMethodRetryHandler());

			if (httpClient.executeMethod(postMethod) == HttpStatus.SC_OK) {
				// 读取内容
				inputStream = postMethod.getResponseBodyAsStream();
				content = IOUtils.toByteArray(inputStream);
			} else {

				System.err.println("Method failed: "
						+ postMethod.getStatusLine());
			}
		} catch (IOException ex) {

			ex.printStackTrace();
		} finally {

			IOUtils.closeQuietly(inputStream);
			// postMethod.releaseConnection();
		}
		return content;
	}

	public static byte[] doGet(HttpClient httpClient, String url,
			Map headerMap, String proxyUrl, int proxyPort) {

		byte[] content = null;
		GetMethod getMethod = new GetMethod(url);

		if (headerMap != null) {

			// 头部请求信息
			if (headerMap != null) {

				Iterator iterator = headerMap.entrySet().iterator();
				while (iterator.hasNext()) {

					Map.Entry entry = (Map.Entry) iterator.next();
					getMethod.addRequestHeader(entry.getKey().toString(), entry
							.getValue().toString());
				}
			}
		}

		if (StringUtils.isNotBlank(proxyUrl)) {

			httpClient.getHostConfiguration().setProxy(proxyUrl, proxyPort);
		}

		// 设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
		getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 10000);
		// postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER ,
		// new DefaultHttpMethodRetryHandler());
		InputStream inputStream = null;
		try {

			if (httpClient.executeMethod(getMethod) == HttpStatus.SC_OK) {

				// 读取内容
				inputStream = getMethod.getResponseBodyAsStream();
				content = IOUtils.toByteArray(inputStream);
			} else {

				System.err.println("Method failed: "
						+ getMethod.getStatusLine());
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {

			IOUtils.closeQuietly(inputStream);
			getMethod.releaseConnection();
		}
		return content;
	}

	public static void main(String[] args) {

		System.out.println("-------------------"
				+ doGetStringResult("http://jrj.com.cn"));
	}

	public static void download(String url, String filePath) {
		HttpClient httpClient = new HttpClient();
		System.out.println(url + "--------");
		/*String start = url.substring(0, url.indexOf("filename="));
		String end = url.substring(url.indexOf("filename=") + 9);

		url = start + "filename=" + URLEncoder.encode(URLDecoder.decode(end));
*/
		// url = URLEncoder.encode(url);
		GetMethod getMethod = new GetMethod(url);

		// 设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
		getMethod.getParams()
				.setParameter(HttpMethodParams.SO_TIMEOUT, 1000000);
		getMethod.setRequestHeader("Host", "file.dl02.zxxk.com");
		// postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER ,
		// new DefaultHttpMethodRetryHandler());
		InputStream inputStream = null;
		File file = new File(filePath);
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(file);

			if (httpClient.executeMethod(getMethod) == HttpStatus.SC_OK) {

				// 读取内容
				inputStream = getMethod.getResponseBodyAsStream();
				byte[] buffer = new byte[1024 * 1024];
				int len = -1;
				while ((len = inputStream.read(buffer)) != -1) {
					fos.write(buffer, 0, len);
					fos.flush();
				}
				fos.close();
				inputStream.close();
			} else {

				System.err.println("Method failed: "
						+ getMethod.getStatusLine());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			getMethod.releaseConnection();
		}
	}

	public static void download(String url, String filePath,Map<String,String> cookies) {
        HttpClient httpClient = new HttpClient();
        System.out.println(url + "--------");
        String start = url.substring(0, url.indexOf("filename="));
        String end = url.substring(url.indexOf("filename=") + 9);

        url = start + "filename=" + URLEncoder.encode(URLDecoder.decode(end));
        
        //url = URLEncoder.encode(url);
        GetMethod getMethod = new GetMethod(url);
        getMethod.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
        
        String cookieStr = "";
        for(String key :cookies.keySet()){
        	cookieStr  += key + "=" + cookies.get(key)+";";
        }
        System.out.println(cookieStr + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        getMethod.setRequestHeader("Cookie", cookieStr);
        //设置成了默认的恢复策略，在发生异常时候将自动重试3次，在这里你也可以设置成自定义的恢复策略
        getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 1000000);
        getMethod.setRequestHeader("Host", "file.dl02.zxxk.com");
        //postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER , new DefaultHttpMethodRetryHandler());
        InputStream inputStream = null;
        File file = new File(filePath);
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(file);

            if (httpClient.executeMethod(getMethod) == HttpStatus.SC_OK) {

                //读取内容
                inputStream = getMethod.getResponseBodyAsStream();
                byte[] buffer = new byte[1024 * 1024];
                int len = -1;
                while ((len = inputStream.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                    fos.flush();
                }
                fos.close();
                inputStream.close();
            } else {

                System.err.println("Method failed: " + getMethod.getStatusLine());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            getMethod.releaseConnection();
        }
    }
}
